home *** CD-ROM | disk | FTP | other *** search
/ C/C++ Users Group Library 1996 July / C-C++ Users Group Library July 1996.iso / listings / v_13_08 / phillip2 / segment.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-06-26  |  35.5 KB  |  1,271 lines

  1.  
  2.    /*********************************************
  3.    *
  4.    *       file d:\cips\segment.c
  5.    *
  6.    *       Functions: This file contains
  7.    *           adaptive_threshold_segmentation
  8.    *           append_stack_files
  9.    *           copy_stack_files
  10.    *           find_peaks
  11.    *           find_valley_point
  12.    *           grow
  13.    *           insert_into_peaks
  14.    *           insert_into_deltas
  15.    *           label_and_check_neighbors
  16.    *           manual_threshold_segmentation
  17.    *           peak_threshold_segmentation
  18.    *           peaks_high_low
  19.    *           push_data_onto_stack_file
  20.    *           pop_data_off_of_stack_file
  21.    *           threshold_image_array
  22.    *           valley_high_low
  23.    *           valley_threshold_segmentation
  24.    *           get_segmentation_options
  25.    *
  26.    *       Purpose:
  27.    *           These functions are part of histogram
  28.    *           based image segmentation.
  29.    *
  30.    *       External Calls:
  31.    *          wtiff.c - round_off_image_size
  32.    *                    create_file_if_needed
  33.    *                    write_array_into_tiff_image
  34.    *          tiff.c - read_tiff_header
  35.    *          rtiff.c - read_tiff_image
  36.    *          numcvrt.c - get_integer
  37.    *                      get_short
  38.    *
  39.    *       Modifications:
  40.    *           October 1992 - created
  41.    *
  42.    ************************************************/
  43.  
  44.  
  45. #include "cips.h"
  46.  
  47.  
  48.    /**************************************************
  49.    *
  50.    *   manual_threshold_segmentation(...
  51.    *
  52.    *   This function segments an image using thresholding
  53.    *   given the hi and low values of the threshold
  54.    *   by the calling routine.  It reads in an image
  55.    *   and writes the result to the output image.
  56.    *
  57.    *   If the segment parameter is 0, you only
  58.    *   threshold the array - you do not segment.
  59.    *
  60.    ***************************************************/
  61.  
  62. manual_threshold_segmentation(in_name, out_name,
  63.                               the_image, out_image,
  64.                               il, ie, ll, le,
  65.                               hi, low, value, segment)
  66.    char   in_name[], out_name[];
  67.    int    il, ie, ll, le, segment;
  68.    short  hi, low, the_image[ROWS][COLS],
  69.           out_image[ROWS][COLS], value;
  70. {
  71.    int    length, width;
  72.    struct tiff_header_struct image_header;
  73.  
  74.    create_file_if_needed(in_name, out_name, out_image);
  75.  
  76.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  77.    threshold_image_array(the_image, out_image,
  78.             hi, low, value);
  79.    if(segment == 1)
  80.       grow(out_image, value);
  81.    write_array_into_tiff_image(out_name, out_image,
  82.                                il, ie, ll, le);
  83.  
  84. }  /* ends manual_threshold_segmentation */
  85.  
  86.  
  87.  
  88.  
  89.  
  90.    /************************************************
  91.    *
  92.    *   peak_threshold_segmentation(...
  93.    *
  94.    *   This function segments an image using
  95.    *   thresholding.  It uses the histogram peaks
  96.    *   to find the hi and low values of the
  97.    *   threshold.
  98.    *
  99.    *   If the segment parameter is 0, you only
  100.    *   threshold the array - you do not segment.
  101.    *
  102.    *************************************************/
  103.  
  104. peak_threshold_segmentation(in_name, out_name,
  105.                             the_image, out_image,
  106.                             il, ie, ll, le,
  107.                             value, segment)
  108.    char   in_name[], out_name[];
  109.    int    il, ie, ll, le, segment;
  110.    short  the_image[ROWS][COLS],
  111.           out_image[ROWS][COLS], value;
  112. {
  113.    int      length, peak1, peak2, width;
  114.    short    hi, low;
  115.    struct   tiff_header_struct image_header;
  116.    unsigned long histogram[GRAY_LEVELS+1];
  117.  
  118.    create_file_if_needed(in_name, out_name, out_image);
  119.  
  120.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  121.    zero_histogram(histogram);
  122.    calculate_histogram(the_image, histogram);
  123.    smooth_histogram(histogram);
  124.    find_peaks(histogram, &peak1, &peak2);
  125.    peaks_high_low(histogram, peak1, peak2,
  126.                   &hi, &low);
  127.    threshold_image_array(the_image, out_image,
  128.                          hi, low, value);
  129.    if(segment == 1)
  130.       grow(out_image, value);
  131.    write_array_into_tiff_image(out_name, out_image,
  132.                                il, ie, ll, le);
  133.  
  134. }  /* ends peak_threshold_segmentation */
  135.  
  136.  
  137.  
  138.  
  139.  
  140.    /************************************************
  141.    *
  142.    *   valley_threshold_segmentation(...
  143.    *
  144.    *   This function segments an image using
  145.    *   thresholding.  It uses the histogram valleys
  146.    *   to find the hi and low values of the
  147.    *   threshold.
  148.    *
  149.    *   If the segment parameter is 0, you only
  150.    *   threshold the array - you do not segment.
  151.    *
  152.    *************************************************/
  153.  
  154. valley_threshold_segmentation(in_name, out_name,
  155.                               the_image, out_image,
  156.                               il, ie, ll, le,
  157.                               value, segment)
  158.    char   in_name[], out_name[];
  159.    int    il, ie, ll, le, segment;
  160.    short  the_image[ROWS][COLS],
  161.           out_image[ROWS][COLS], value;
  162. {
  163.    int      length, peak1, peak2, width;
  164.    short    hi, low;
  165.    struct   tiff_header_struct image_header;
  166.    unsigned long histogram[GRAY_LEVELS+1];
  167.  
  168.    create_file_if_needed(in_name, out_name, out_image);
  169.  
  170.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  171.    zero_histogram(histogram);
  172.    calculate_histogram(the_image, histogram);
  173.    smooth_histogram(histogram);
  174.    find_peaks(histogram, &peak1, &peak2);
  175.    valley_high_low(histogram, peak1, peak2,
  176.                    &hi, &low);
  177.    threshold_image_array(the_image, out_image,
  178.                          hi, low, value);
  179.    if(segment == 1)
  180.       grow(out_image, value);
  181.    write_array_into_tiff_image(out_name, out_image,
  182.                                il, ie, ll, le);
  183.  
  184. }  /* ends valley_threshold_segmentation */
  185.  
  186.  
  187.  
  188.  
  189.  
  190.    /************************************************
  191.    *
  192.    *   adaptive_threshold_segmentation(...
  193.    *
  194.    *   This function segments an image using
  195.    *   thresholding.  It uses two passes
  196.    *   to find the hi and low values of the
  197.    *   threshold.  The first pass uses the peaks
  198.    *   of the histogram to find the hi and low
  199.    *   threshold values.  It thresholds the image
  200.    *   using these hi lows and calculates the means
  201.    *   of the object and background.  Then we use
  202.    *   these means as new peaks to calculate new
  203.    *   hi and low values.  Finally, we threshold
  204.    *   the image again using these second hi low
  205.    *   hi low values.
  206.    *
  207.    *   If the segment parameter is 0, you only
  208.    *   threshold the array - you do not segment.
  209.    *
  210.    *************************************************/
  211.  
  212. adaptive_threshold_segmentation(in_name, out_name,
  213.                                 the_image, out_image,
  214.                                 il, ie, ll, le,
  215.                                 value, segment)
  216.    char   in_name[], out_name[];
  217.    int    il, ie, ll, le, segment;
  218.    short  the_image[ROWS][COLS],
  219.           out_image[ROWS][COLS], value;
  220. {
  221.    int      length, peak1, peak2, width;
  222.    short    background, hi, low, object;
  223.    struct   tiff_header_struct image_header;
  224.    unsigned long histogram[GRAY_LEVELS+1];
  225.  
  226.    create_file_if_needed(in_name, out_name, out_image);
  227.  
  228.    read_tiff_image(in_name, the_image, il, ie, ll, le);
  229.    zero_histogram(histogram);
  230.    calculate_histogram(the_image, histogram);
  231.    smooth_histogram(histogram);
  232.    find_peaks(histogram, &peak1, &peak2);
  233.    peaks_high_low(histogram, peak1, peak2,
  234.                   &hi, &low);
  235.    threshold_and_find_means(the_image, out_image,
  236.                             hi, low, value,
  237.                             &object, &background);
  238.    peaks_high_low(histogram, object, background,
  239.                   &hi, &low);
  240.    threshold_image_array(the_image, out_image,
  241.                          hi, low, value);
  242.    if(segment == 1)
  243.       grow(out_image, value);
  244.    write_array_into_tiff_image(out_name, out_image,
  245.                                il, ie, ll, le);
  246.  
  247. }  /* ends adaptive_threshold_segmentation */
  248.  
  249.  
  250.  
  251.  
  252.  
  253.    /**************************************************
  254.    *
  255.    *   threshold_image_array(...
  256.    *
  257.    *   This function thresholds an input image array
  258.    *   and produces a binary output image array.
  259.    *   If the pixel in the input array is between
  260.    *   the hi and low values, then it is set to value.
  261.    *   Otherwise, it is set to 0.
  262.    *
  263.    ***************************************************/
  264.  
  265.  
  266. threshold_image_array(in_image, out_image, hi, low, value)
  267.    short hi, low, in_image[ROWS][COLS],
  268.          out_image[ROWS][COLS], value;
  269. {
  270.    int   counter = 0, i, j;
  271.    for(i=0; i<ROWS; i++){
  272.       for(j=0; j<COLS; j++){
  273.          if(in_image[i][j] >= low  &&
  274.             in_image[i][j] <= hi){
  275.             out_image[i][j] = value;
  276.             counter++;
  277.          }
  278.          else
  279.             out_image[i][j] = 0;
  280.       }  /* ends loop over j */
  281.    }  /* ends loop over i */
  282.    printf("\n\tTIA> set %d points", counter);
  283. }  /* ends threshold_image_array */
  284.  
  285.  
  286.  
  287.  
  288.  
  289.    /**************************************************
  290.    *
  291.    *   threshold_and_find_means(...
  292.    *
  293.    *   This function thresholds an input image array
  294.    *   and produces a binary output image array.
  295.    *   If the pixel in the input array is between
  296.    *   the hi and low values, then it is set to value.
  297.    *   Otherwise, it is set to 0.
  298.    *
  299.    ***************************************************/
  300.  
  301. threshold_and_find_means(in_image, out_image, hi,
  302.                          low, value, object_mean,
  303.                          background_mean)
  304.    short *background_mean, hi, low,
  305.          in_image[ROWS][COLS], *object_mean,
  306.          out_image[ROWS][COLS], value;
  307. {
  308.    int      counter = 0,
  309.             i,
  310.             j;
  311.    unsigned long object     = 0,
  312.                  background = 0;
  313.  
  314.    for(i=0; i<ROWS; i++){
  315.       for(j=0; j<COLS; j++){
  316.          if(in_image[i][j] >= low  &&
  317.             in_image[i][j] <= hi){
  318.             out_image[i][j] = value;
  319.             counter++;
  320.             object = object + in_image[i][j];
  321.          }
  322.          else{
  323.             out_image[i][j] = 0;
  324.             background      = background + in_image[i][j];
  325.          }
  326.       }  /* ends loop over j */
  327.    }  /* ends loop over i */
  328.    object     = object/counter;
  329.    background = background/((ROWS*COLS)-counter);
  330.    *object_mean     = (short)(object);
  331.    *background_mean = (short)(background);
  332.    printf("\n\tTAFM> set %d points", counter);
  333.    printf("\n\tTAFM> object=%d background=%d",
  334.           *object_mean, *background_mean);
  335. }  /* ends threshold_and_find_means */
  336.  
  337.  
  338.  
  339.  
  340.  
  341.     /**********************************************
  342.     *
  343.     *  grow(...
  344.     *
  345.     *  This function is an object detector.
  346.     *  Its input is an binary image array
  347.     *  containing 0's and value's.
  348.     *  It searches through the image and connects
  349.     *  the adjacent values.
  350.     *
  351.     ***********************************************/
  352.  
  353. grow(binary, value)
  354.    short binary[ROWS][COLS],
  355.          value;
  356. {
  357.    char name[80];
  358.  
  359.    int first_call,
  360.        i,
  361.        j,
  362.        object_found,
  363.        pointer,
  364.        pop_i,
  365.        pop_j,
  366.        stack_empty,
  367.        stack_file_in_use;
  368.  
  369.    short g_label, stack[STACK_SIZE][2];
  370.  
  371.             /*************************************
  372.             *
  373.             *   Now begin the process of growing
  374.             *   regions.
  375.             *
  376.             **************************************/
  377.  
  378.    g_label       = 2;
  379.    object_found  = 0;
  380.    first_call    = 1;
  381.  
  382.    for(i=0; i<ROWS; i++){
  383.       for(j=0; j<COLS; j++){
  384.  
  385.          stack_file_in_use =  0;
  386.          stack_empty       =  1;
  387.          pointer           = -1;
  388.  
  389.                /**********************************
  390.                *
  391.                *  Search for the first pixel of
  392.                *  a region.
  393.                *
  394.                ***********************************/
  395.  
  396.          if(binary[i][j] == value){
  397.             label_and_check_neighbor(binary, stack, 
  398.                       g_label, &stack_empty, &pointer, 
  399.                       i, j, value, &stack_file_in_use,
  400.                       &first_call);
  401.             object_found = 1;
  402.          }  /* ends if binary[i]j] == value */
  403.  
  404.                /*****************************
  405.                *
  406.                *  If the stack is not empty,
  407.                *  pop the coordinates of
  408.                *  the pixel off the stack
  409.                *  and check its 8 neighbors.
  410.                *
  411.                *******************************/
  412.  
  413.          while(stack_empty == 0){
  414.             pop_i = stack[pointer][0]; /* POP       */
  415.             pop_j = stack[pointer][1]; /* OPERATION */
  416.             --pointer;
  417.             if(pointer <= 0){
  418.                if(stack_file_in_use){
  419.                   pop_data_off_of_stack_file(
  420.                                  stack,
  421.                                  &pointer,
  422.                                  &stack_file_in_use);
  423.                }  /* ends if stack_file_in_use  */
  424.                else{
  425.                   pointer     = 0;
  426.                   stack_empty = 1;
  427.                }  /* ends else stack file is
  428.                      not in use  */
  429.             }  /*  ends if point <= 0  */
  430.  
  431.             label_and_check_neighbor(binary,
  432.                         stack, g_label,
  433.                         &stack_empty,
  434.                         &pointer, pop_i,
  435.                         pop_j, value,
  436.                         &stack_file_in_use,
  437.                         &first_call);
  438.          }  /* ends while stack_empty == 0 */
  439.  
  440.          if(object_found == 1){
  441.             object_found = 0;
  442.             ++g_label;
  443.          }  /* ends if object_found == 1 */
  444.  
  445.       }   /* ends loop over j */
  446.    }  /* ends loop over i */
  447.  
  448.    printf("\nGROW> found %d objects", g_label);
  449.  
  450. } /* ends grow  */
  451.  
  452.  
  453.  
  454.  
  455.  
  456.    /********************************************
  457.    *
  458.    *  label_and_check_neighbors(...
  459.    *
  460.    *  This function labels a pixel with an object
  461.    *  label and then checks the pixel's 8
  462.    *  neighbors.  If any of the neigbors are
  463.    *  set, then they are also labeled.
  464.    *
  465.    ***********************************************/
  466.  
  467. label_and_check_neighbor(binary_image, stack,
  468.                          g_label, stack_empty,
  469.                          pointer, r, e, value,
  470.                          stack_file_in_use,
  471.                          first_call)
  472. int   e,
  473.       *first_call,
  474.       *pointer,
  475.       r,
  476.       *stack_empty,
  477.       *stack_file_in_use;
  478.  
  479. short binary_image[ROWS][COLS],
  480.       g_label,
  481.       stack[STACK_SIZE][2],
  482.       value;
  483. {
  484.    int already_labeled = 0,
  485.        i, j;
  486.  
  487.    if (binary_image[r][e] == g_label)
  488.       already_labeled = 1;
  489.  
  490.    binary_image[r][e] = g_label;
  491.  
  492.       /***************************************
  493.       *
  494.       *   Look at the 8 neighors of the
  495.       *   point r,e.
  496.       *
  497.       *   Ensure the points you are checking
  498.       *   are in the image, i.e. not less
  499.       *   than zero and not greater than
  500.       *   ROWS-1 or COLS-1.
  501.       *
  502.       ***************************************/
  503.  
  504.    for(i=(r-1); i<=(r+1); i++){
  505.       for(j=(e-1); j<=(e+1); j++){
  506.  
  507.          if((i>=0)   &&
  508.             (i<=ROWS-1)  &&
  509.             (j>=0)   &&
  510.             (j<=COLS-1)){
  511.  
  512.             if(binary_image[i][j] == value){
  513.                *pointer           = *pointer + 1;
  514.                stack[*pointer][0] = i; /* PUSH      */
  515.                stack[*pointer][1] = j; /* OPERATION */
  516.                *stack_empty       = 0;
  517.  
  518.                if(*pointer >= (STACK_SIZE -
  519.                                STACK_FILE_LENGTH)){
  520.                   push_data_onto_stack_file(stack,
  521.                             pointer, first_call);
  522.                   *stack_file_in_use = 1;
  523.                }  /* ends if *pointer >=
  524.                      STACK_SIZE - STACK_FILE_LENGTH*/
  525.  
  526.             }  /* end of if binary_image == value */
  527.          }  /* end if i and j are on the image */
  528.       }  /* ends loop over i rows           */
  529.    }  /* ends loop over j columns        */
  530. }  /* ends label_and_check_neighbors  */
  531.  
  532.  
  533.  
  534.  
  535.  
  536.    /****************************************
  537.    *
  538.    *   push_data_onto_stack_file(...
  539.    *
  540.    *   This function takes the stack array
  541.    *   and pushes it onto the stack file.
  542.    *
  543.    *****************************************/
  544.  
  545. push_data_onto_stack_file(stack, pointer, first_call)
  546.    int   *first_call, *pointer;
  547.    short stack[STACK_SIZE][2];
  548. {
  549.    char  backup_file_name[MAX_NAME_LENGTH];
  550.    FILE  *backup_file_pointer, *stack_file_pointer;
  551.    int   diff, i;
  552.    short holder[STACK_FILE_LENGTH][2];
  553.  
  554.    printf("\nSFO> Start of push_data_onto_stack ");
  555.  
  556.    diff = STACK_SIZE - STACK_FILE_LENGTH;
  557.  
  558.        /*******************************************
  559.        *
  560.        *   Copy the elements to be stored to the
  561.        *   stack file into holder
  562.        *
  563.        ********************************************/
  564.  
  565.    for(i=0; i<STACK_FILE_LENGTH; i++){
  566.       holder[i][0] = stack[i][0];
  567.       holder[i][1] = stack[i][1];
  568.    }
  569.  
  570.        /*******************************************
  571.        *
  572.        *   Move the elements of the stack down
  573.        *
  574.        *******************************************/
  575.  
  576.    for(i=0; i<diff; i++){
  577.       stack[i][0] = stack[i + STACK_FILE_LENGTH][0];
  578.       stack[i][1] = stack[i + STACK_FILE_LENGTH][1];
  579.    }
  580.  
  581.        /*******************************************
  582.        *
  583.        *   Fill the top of the stack with zeros
  584.        *
  585.        *******************************************/
  586.  
  587.    for(i=diff; i<STACK_SIZE; i++){
  588.       stack[i][0] = 0;
  589.       stack[i][1] = 0;
  590.    }
  591.  
  592.    *pointer = *pointer - STACK_FILE_LENGTH;
  593.  
  594.    /************************************************
  595.    *
  596.    *   Store the holder array into the stack file.
  597.    *   Open the stack file for writing in binary
  598.    *   mode. If the file does not exist it will be
  599.    *   created. If the file does exist it will be
  600.    *   over written.
  601.    *
  602.    *   PUSH - IF first_time == 1 then write to stack
  603.    *          ELSE write to stack.bak
  604.    *          append stack onto stack.bak
  605.    *          copy stack.bak to stack
  606.    *          this has the effect of writing
  607.    *          to the beginning of the stack.
  608.    *
  609.    ************************************************/
  610.  
  611.    if(*first_call == 1){
  612.  
  613.       *first_call = *first_call + 1;
  614.       if((stack_file_pointer = fopen(STACK_FILE,"wb"))
  615.                                      == NULL)
  616.          printf("\nSFO> Could not open stack file");
  617.       else{
  618.          /*printf("\n\nSFO> Writing to stack file");*/
  619.          fwrite(holder, sizeof(holder),
  620.                 1, stack_file_pointer);
  621.          fclose(stack_file_pointer);
  622.       }  /*  ends else could not open stack_file  */
  623.  
  624.    }  /*  ends if *first_call == 1  */
  625.    else{  /* else stack file has been used already  */
  626.       strcpy(backup_file_name, STACK_FILE);
  627.       strcat(backup_file_name, ".bak");
  628.       if((backup_file_pointer =
  629.           fopen(backup_file_name, "wb")) == NULL)
  630.          printf("\nSFO> Could not open backup file");
  631.       else{
  632.          /*printf("\n\nSFO> Writing to backup file");*/
  633.          fwrite(holder, sizeof(holder),
  634.                 1, backup_file_pointer);
  635.          fclose(backup_file_pointer);
  636.       }  /*  ends else could not open backup_file  */
  637.  
  638.       append_stack_files(backup_file_name,
  639.                          STACK_FILE, holder);
  640.       copy_stack_files(backup_file_name,
  641.                        STACK_FILE, holder);
  642.  
  643.    }  /*  ends else first_call != 1  */
  644.  
  645.    printf("--- End of push_data_onto_stack");
  646.  
  647. }  /* ends push_data_onto_stack_file  */
  648.  
  649.  
  650.  
  651.  
  652.  
  653.    /****************************************
  654.    *
  655.    *   pop_data_off_of_stack_file(...
  656.    *
  657.    *   This function pops the stack array
  658.    *   off of the stack file.
  659.    *
  660.    *****************************************/
  661.  
  662. pop_data_off_of_stack_file(stack, pointer,
  663.                            stack_file_in_use)
  664.    int   *pointer, *stack_file_in_use;
  665.    short stack[STACK_SIZE][2];
  666. {
  667.    char  backup_file_name[MAX_NAME_LENGTH];
  668.    FILE  *backup_file_pointer, *stack_file_pointer;
  669.    int   i;
  670.    long  write_counter;
  671.    short holder[STACK_FILE_LENGTH][2],
  672.          holder2[STACK_FILE_LENGTH][2];
  673.  
  674.        /*******************************************
  675.        *
  676.        *   POP - Read 1 time from stack
  677.        *         Copy the remainder of stack to
  678.        *            stack.bak
  679.        *         Copy stack.bak to stack
  680.        *         This has the effect of popping off
  681.        *         of the stack.
  682.        *
  683.        *   Read the holder array from the stack file.
  684.        *   Open the stack file for reading in binary
  685.        *   mode.
  686.        *
  687.        *   If it requires more than one write to
  688.        *   copy the remainder of stack to
  689.        *   stack.bak then there is still data in the
  690.        *   stack file so set stack_file_in_use = 1.
  691.        *   Else set it to 0.
  692.        *
  693.        **********************************************/
  694.  
  695.    printf("\nSFO> Start of pop_data_off_of_stack ");
  696.    write_counter = 0;
  697.  
  698.    strcpy(backup_file_name, STACK_FILE);
  699.    strcat(backup_file_name, ".bak");
  700.  
  701.    if( (stack_file_pointer =
  702.           fopen(STACK_FILE, "rb")) == NULL)
  703.       printf("\nSFO> Could not open stack file");
  704.    else{
  705.       /*printf("\n\nSFO> Reading from stack file");*/
  706.       fread(holder, sizeof(holder),
  707.             1, stack_file_pointer);
  708.  
  709.       backup_file_pointer =
  710.             fopen(backup_file_name, "wb");
  711.       while( fread(holder2, sizeof(holder2),
  712.                    1, stack_file_pointer) ){
  713.          fwrite(holder2, sizeof(holder2),
  714.                 1, backup_file_pointer);
  715.          ++write_counter;
  716.       }  /* ends while reading  */
  717.       if(write_counter > 0)
  718.          *stack_file_in_use = 1;
  719.       else
  720.          *stack_file_in_use = 0;
  721.  
  722.       fclose(backup_file_pointer);
  723.       fclose(stack_file_pointer);
  724.    }  /* ends else could not open stack file  */
  725.  
  726.    copy_stack_files(backup_file_name,
  727.                     STACK_FILE, holder2);
  728.  
  729.    for(i=0; i<STACK_FILE_LENGTH; i++){
  730.       stack[i][0] = holder[i][0];
  731.       stack[i][1] = holder[i][1];
  732.    }
  733.  
  734.    *pointer = *pointer + STACK_FILE_LENGTH - 1;
  735.  
  736.    printf("--- End of pop_data_off_of_stack");
  737. }  /* ends pop_data_off_of_stack_file  */
  738.  
  739.  
  740.  
  741.  
  742.  
  743.    /*********************************************
  744.    *
  745.    *   append_stack_files(...
  746.    *
  747.    *   Append the second file onto the end
  748.    *   of the first.
  749.    *
  750.    ***********************************************/
  751.  
  752. append_stack_files(first_file, second_file, holder)
  753.    char first_file[], second_file[];
  754.    short holder[STACK_FILE_LENGTH][2];
  755. {
  756.    FILE  *first, *second;
  757.    int   i;
  758.  
  759.    if((first = fopen(first_file, "r+b")) == NULL)
  760.       printf("\n\nSFO> Cannot open file %s",
  761.              first_file);
  762.  
  763.    if((second = fopen(second_file, "rb")) == NULL)
  764.       printf("\n\nSFO> Cannot open file %s",
  765.              second_file);
  766.  
  767.           /*****************************************
  768.           *
  769.           *  Seek to the end of the first file and
  770.           *  to the beginning of the second file.
  771.           *
  772.           *******************************************/
  773.  
  774.    fseek(first, 0L, 2);
  775.    fseek(second, 0L, 0);
  776.  
  777.    while(fread(holder, sizeof(holder), 1, second) ){
  778.       fwrite(holder, sizeof(holder), 1, first);
  779.    }  /* ends while reading  */
  780.  
  781.    fclose(first);
  782.    fclose(second);
  783.  
  784. }  /*  ends append_stack_files  */
  785.  
  786.  
  787.  
  788.  
  789.  
  790.    /********************************************
  791.    *
  792.    *   copy_stack_files(...
  793.    *
  794.    *   Copy the first file to the second.
  795.    *
  796.    **********************************************/
  797.  
  798. copy_stack_files(first_file, second_file, holder)
  799.    char first_file[], second_file[];
  800.    short holder[STACK_FILE_LENGTH][2];
  801. {
  802.    FILE  *first, *second;
  803.    int   i;
  804.  
  805.    if( (first = fopen(first_file, "rb")) == NULL)
  806.       printf("\n\nSFO> Cannot open file %s",
  807.              first_file);
  808.  
  809.    if( (second = fopen(second_file, "wb")) == NULL)
  810.       printf("\n\nSFO> Cannot open file %s",
  811.              second_file);
  812.  
  813.           /******************************************
  814.           *
  815.           *  Seek to the beginning of the first file.
  816.           *
  817.           *******************************************/
  818.  
  819.    fseek(first, 0L, 0);
  820.  
  821.    while( fread(holder, sizeof(holder), 1, first) ){
  822.       fwrite(holder, sizeof(holder), 1, second);
  823.    }  /* ends while reading  */
  824.  
  825.    fclose(first);
  826.    fclose(second);
  827.  
  828. }  /*  ends copy_stack_files */
  829.  
  830.  
  831.  
  832.  
  833.    /********************************************
  834.    *
  835.    *   find_peaks(...
  836.    *
  837.    *   This function looks through the histogram
  838.    *   array and finds the two highest peaks.
  839.    *   The peaks must be separated, cannot be
  840.    *   next to each other, by a spacing defined
  841.    *   in cips.h.
  842.    *
  843.    *   The peaks array holds the peak value
  844.    *   in the first place and its location in
  845.    *   the second place.
  846.    *
  847.    *********************************************/
  848.  
  849. find_peaks(histogram, peak1, peak2)
  850.    unsigned long histogram[];
  851.    int *peak1, *peak2;
  852. {
  853.    int distance[PEAKS], peaks[PEAKS][2];
  854.    int i, j=0, max=0, max_place=0;
  855.  
  856.    for(i=0; i<PEAKS; i++){
  857.       distance[i] =  0;
  858.       peaks[i][0] = -1;
  859.       peaks[i][1] = -1;
  860.    }
  861.  
  862.    for(i=0; i<=GRAY_LEVELS; i++){
  863.       max       = histogram[i];
  864.       max_place = i;
  865.       insert_into_peaks(peaks, max, max_place);
  866.    }  /* ends loop over i */
  867.  
  868.    for(i=1; i<PEAKS; i++){
  869.       distance[i] = peaks[0][1] - peaks[i][1];
  870.       if(distance[i] < 0)
  871.          distance[i] = distance[i]*(-1);
  872.    }
  873.  
  874.    *peak1 = peaks[0][1];
  875.    for(i=PEAKS-1; i>0; i--)
  876.     if(distance[i] > PEAK_SPACE) *peak2 = peaks[i][1];
  877.  
  878. }  /* ends find_peaks */
  879.  
  880.  
  881.  
  882.  
  883.  
  884.    /********************************************
  885.    *
  886.    *   insert_into_peaks(...
  887.    *
  888.    *   This function takes a value and its
  889.    *   place in the histogram and inserts them
  890.    *   into a peaks array.  This helps us rank
  891.    *   the the peaks in the histogram.
  892.    *
  893.    *   The objective is to build a list of
  894.    *   histogram peaks and thier locations.
  895.    *
  896.    *   The peaks array holds the peak value
  897.    *   in the first place and its location in
  898.    *   the second place.
  899.    *
  900.    *********************************************/
  901.  
  902. insert_into_peaks(peaks, max, max_place)
  903.    int max, max_place, peaks[PEAKS][2];
  904. {
  905.    int i, j;
  906.  
  907.       /* first case */
  908.    if(max > peaks[0][0]){
  909.       for(i=PEAKS-1; i>0; i--){
  910.          peaks[i][0] = peaks[i-1][0];
  911.          peaks[i][1] = peaks[i-1][1];
  912.       }
  913.       peaks[0][0] = max;
  914.       peaks[0][1] = max_place;
  915.    }  /* ends if */
  916.  
  917.       /* middle cases */
  918.    for(j=0; j<PEAKS-3; j++){
  919.       if(max < peaks[j][0]  && max > peaks[j+1][0]){
  920.          for(i=PEAKS-1; i>j+1; i--){
  921.             peaks[i][0] = peaks[i-1][0];
  922.             peaks[i][1] = peaks[i-1][1];
  923.          }
  924.          peaks[j+1][0] = max;
  925.          peaks[j+1][1] = max_place;
  926.       }  /* ends if */
  927.    }  /* ends loop over j */
  928.       /* last case */
  929.    if(max < peaks[PEAKS-2][0]  && 
  930.       max > peaks[PEAKS-1][0]){
  931.       peaks[PEAKS-1][0] = max;
  932.       peaks[PEAKS-1][1] = max_place;
  933.    }  /* ends if */
  934.  
  935. }  /* ends insert_into_peaks */
  936.  
  937.  
  938.  
  939.  
  940.  
  941.    /********************************************
  942.    *
  943.    *   peaks_high_low(...
  944.    *
  945.    *   This function uses the histogram array
  946.    *   and the peaks to find the best high and
  947.    *   low threshold values for the threshold
  948.    *   function.  You want the hi and low values
  949.    *   so that you will threshold the image around
  950.    *   the smaller of the two "humps" in the
  951.    *   histogram.  This is because the smaller
  952.    *   hump represents the objects while the
  953.    *   larger hump represents the background.
  954.    *
  955.    *********************************************/
  956.  
  957. peaks_high_low(histogram, peak1, peak2, hi, low)
  958.    int  peak1, peak2;
  959.    short *hi, *low;
  960.    unsigned long histogram[];
  961. {
  962.    int i, mid_point;
  963.    unsigned long sum1 = 0, sum2 = 0;
  964.  
  965.    if(peak1 > peak2)
  966.       mid_point = ((peak1 - peak2)/2) + peak2;
  967.    if(peak1 < peak2)
  968.       mid_point = ((peak2 - peak1)/2) + peak1;
  969.  
  970.    for(i=0; i<mid_point; i++)
  971.       sum1 = sum1 + histogram[i];
  972.  
  973.    for(i=mid_point; i<=GRAY_LEVELS; i++)
  974.       sum2 = sum2 + histogram[i];
  975.    if(sum1 >= sum2){
  976.       *low = mid_point;
  977.       *hi  = GRAY_LEVELS;
  978.    }
  979.    else{
  980.       *low = 0;
  981.       *hi  = mid_point;
  982.    }
  983.  
  984. }  /* ends peaks_high_low */
  985.  
  986.  
  987.  
  988.  
  989.  
  990.       /********************************************
  991.       *
  992.       *   valley_high_low(...
  993.       *
  994.       *   This function uses the histogram array
  995.       *   and the valleys to find the best high and
  996.       *   low threshold values for the threshold
  997.       *   function.  You want the hi and low values
  998.       *   so that you will threshold the image around
  999.       *   the smaller of the two "humps" in the
  1000.       *   histogram.  This is because the smaller
  1001.       *   hump represents the objects while the
  1002.       *   larger hump represents the background.
  1003.       *
  1004.       *********************************************/
  1005.  
  1006. valley_high_low(histogram, peak1, peak2, hi, low)
  1007.    int  peak1, peak2;
  1008.    short *hi, *low;
  1009.    unsigned long histogram[];
  1010. {
  1011.    int  i, valley_point;
  1012.    unsigned long sum1 = 0, sum2 = 0;
  1013.  
  1014.    find_valley_point(histogram, peak1, peak2,
  1015.                      &valley_point);
  1016.    /*printf("\nVHL> valley point is %d",
  1017.             valley_point);*/
  1018.  
  1019.    for(i=0; i<valley_point; i++)
  1020.       sum1 = sum1 + histogram[i];
  1021.    for(i=valley_point; i<=GRAY_LEVELS; i++)
  1022.       sum2 = sum2 + histogram[i];
  1023.  
  1024.    if(sum1 >= sum2){
  1025.       *low = valley_point;
  1026.       *hi  = GRAY_LEVELS;
  1027.    }
  1028.    else{
  1029.       *low = 0;
  1030.       *hi  = valley_point;
  1031.    }
  1032.  
  1033. }  /* ends valley_high_low */
  1034.  
  1035.  
  1036.  
  1037.  
  1038.  
  1039.    /********************************************
  1040.    *
  1041.    *   find_valley_point(...
  1042.    *
  1043.    *   This function finds the low point of
  1044.    *   the valley between two peaks in a
  1045.    *   histogram.  It starts at the lowest
  1046.    *   peak and works its way up to the
  1047.    *   highest peak.  Along the way, it looks
  1048.    *   at each point in the histogram and inserts
  1049.    *   them into a list of points.  When done,
  1050.    *   it has the location of the smallest histogram
  1051.    *   point - that is the valley point.
  1052.    *
  1053.    *   The deltas array holds the delta value
  1054.    *   in the first place and its location in
  1055.    *   the second place.
  1056.    *
  1057.    *********************************************/
  1058.  
  1059. find_valley_point(histogram, peak1, 
  1060.                   peak2, valley_point)
  1061.    int  peak1, peak2, *valley_point;
  1062.    unsigned long histogram[];
  1063. {
  1064.    int  deltas[PEAKS][2], delta_hist, i;
  1065.  
  1066.    for(i=0; i<PEAKS; i++){
  1067.       deltas[i][0] = 10000;
  1068.       deltas[i][1] =    -1;
  1069.    }
  1070.  
  1071.    if(peak1 < peak2){
  1072.       for(i=peak1+1; i<peak2; i++){
  1073.          delta_hist = (int)(histogram[i]);
  1074.          insert_into_deltas(deltas, delta_hist, i);
  1075.       }  /* ends loop over i */
  1076.    }  /* ends if peak1 < peak2 */
  1077.  
  1078.    if(peak2 < peak1){
  1079.       for(i=peak2+1; i<peak1; i++){
  1080.          delta_hist = (int)(histogram[i]);
  1081.          insert_into_deltas(deltas, delta_hist, i);
  1082.       }  /* ends loop over i */
  1083.    }  /* ends if peak2 < peak1 */
  1084.  
  1085.    *valley_point = deltas[0][1];
  1086.  
  1087. }  /* ends find_valley_point */
  1088.  
  1089.  
  1090.  
  1091.  
  1092.  
  1093.  
  1094.    /********************************************
  1095.    *
  1096.    *   insert_into_deltas(...
  1097.    *
  1098.    *   This function inserts histogram deltas
  1099.    *   into a deltas array.  The smallest delta
  1100.    *   will be at the top of the array.
  1101.    *
  1102.    *   The objective is to build a list of
  1103.    *   histogram area deltas and thier locations.
  1104.    *
  1105.    *   The deltas array holds the delta value
  1106.    *   in the first place and its location in
  1107.    *   the second place.
  1108.    *
  1109.    *********************************************/
  1110.  
  1111. insert_into_deltas(deltas, value, place)
  1112.    int value, place, deltas[PEAKS][2];
  1113. {
  1114.    int i, j;
  1115.  
  1116.       /* first case */
  1117.    if(value < deltas[0][0]){
  1118.       for(i=PEAKS-1; i>0; i--){
  1119.          deltas[i][0] = deltas[i-1][0];
  1120.          deltas[i][1] = deltas[i-1][1];
  1121.       }
  1122.       deltas[0][0] = value;
  1123.       deltas[0][1] = place;
  1124.    }  /* ends if */
  1125.  
  1126.       /* middle cases */
  1127.    for(j=0; j<PEAKS-3; j++){
  1128.       if(value > deltas[j][0]  &&
  1129.          value < deltas[j+1][0]){
  1130.          for(i=PEAKS-1; i>j+1; i--){
  1131.             deltas[i][0] = deltas[i-1][0];
  1132.             deltas[i][1] = deltas[i-1][1];
  1133.          }
  1134.          deltas[j+1][0] = value;
  1135.          deltas[j+1][1] = place;
  1136.       }  /* ends if */
  1137.    }  /* ends loop over j */
  1138.  
  1139.       /* last case */
  1140.    if(value > deltas[PEAKS-2][0]  &&
  1141.       value < deltas[PEAKS-1][0]){
  1142.       deltas[PEAKS-1][0] = value;
  1143.       deltas[PEAKS-1][1] = place;
  1144.    }  /* ends if */
  1145.  
  1146. }  /* ends insert_into_deltas */
  1147.  
  1148.  
  1149.  
  1150.  
  1151.  
  1152.    /********************************************
  1153.    *
  1154.    *   get_segmentation_options(...
  1155.    *
  1156.    *   This function interacts with the user
  1157.    *   to obtain the options for image
  1158.    *   segmentation.
  1159.    *
  1160.    *********************************************/
  1161.  
  1162.  
  1163. get_segmentation_options(method, hi, low, value)
  1164.    char   method[];
  1165.    short  *hi, *low, *value;
  1166. {
  1167.    int   i, not_finished = 1, response;
  1168.  
  1169.    while(not_finished){
  1170.       printf(
  1171.          "\n\nThe image segmentation options are:\n");
  1172.       printf("\n\t1. Method is %s", method);
  1173.       printf("\n\t   (options are manual peaks");
  1174.       printf(        " valleys adapative)");
  1175.       printf("\n\t2. Value is %d", *value);
  1176.       printf("\n\t3. Hi    is %d", *hi);
  1177.       printf("\n\t4. Low   is %d", *low);
  1178.       printf("\n\t   Hi and Low needed only for");
  1179.       printf(        " manual method");
  1180.       printf("\n\nEnter choice (0 = no change):_\b");
  1181.  
  1182.       get_integer(&response);
  1183.  
  1184.       if(response == 0)
  1185.          not_finished = 0;
  1186.  
  1187.       if(response == 1){
  1188.          printf("\nEnter method (options are:");
  1189.          printf(" manual peaks valleys adaptive)\n\t");
  1190.          gets(method);
  1191.       }
  1192.  
  1193.       if(response == 2){
  1194.          printf("\nEnter value: ___\b\b\b");
  1195.          get_short(value);
  1196.       }
  1197.  
  1198.       if(response == 3){
  1199.          printf("\nEnter hi: ___\b\b\b");
  1200.          get_short(hi);
  1201.       }
  1202.       if(response == 4){
  1203.          printf("\nEnter low: ___\b\b\b");
  1204.          get_short(low);
  1205.       }
  1206.  
  1207.    }  /* ends while not_finished */
  1208. }  /* ends get_segmentation_options */
  1209.  
  1210.  
  1211.  
  1212.  
  1213.  
  1214.  
  1215.    /********************************************
  1216.    *
  1217.    *   get_threshold_options(...
  1218.    *
  1219.    *   This function interacts with the user
  1220.    *   to obtain the options for image
  1221.    *   threshold.
  1222.    *
  1223.    *********************************************/
  1224.  
  1225.  
  1226. get_threshold_options(method, hi, low, value)
  1227.    char   method[];
  1228.    short  *hi, *low, *value;
  1229. {
  1230.    int   i, not_finished = 1, response;
  1231.  
  1232.    while(not_finished){
  1233.       printf("\n\nThe image threshold options are:\n");
  1234.       printf("\n\t1. Method is %s", method);
  1235.       printf("\n\t   (options are manual peaks");
  1236.       printf(        " valleys adapative)");
  1237.       printf("\n\t2. Value is %d", *value);
  1238.       printf("\n\t3. Hi    is %d", *hi);
  1239.       printf("\n\t4. Low   is %d", *low);
  1240.       printf("\n\t   Hi and Low needed only for");
  1241.       printf(        " manual method");
  1242.       printf("\n\nEnter choice (0 = no change):_\b");
  1243.  
  1244.       get_integer(&response);
  1245.  
  1246.       if(response == 0)
  1247.          not_finished = 0;
  1248.  
  1249.       if(response == 1){
  1250.          printf("\nEnter method (options are:");
  1251.          printf(" manual peaks valleys adaptive)\n\t");
  1252.          gets(method);
  1253.       }
  1254.  
  1255.       if(response == 2){
  1256.          printf("\nEnter value: ___\b\b\b");
  1257.          get_short(value);
  1258.       }
  1259.  
  1260.       if(response == 3){
  1261.          printf("\nEnter hi: ___\b\b\b");
  1262.          get_short(hi);
  1263.       }
  1264.       if(response == 4){
  1265.          printf("\nEnter low: ___\b\b\b");
  1266.          get_short(low);
  1267.       }
  1268.  
  1269.    }  /* ends while not_finished */
  1270. }  /* ends get_threshold_options */
  1271.